using System;
using System.Collections.Generic;
using System.Linq;
using KaroEngine;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
using System.Timers;


namespace KaroGame.FrontEnd
{
    public enum HudPosition
    {
        Top,
        Bottom,
        Left,
        Right
    }

    /// <summary>
    /// This is a game component that implements IUpdateable.
    /// </summary>
    public class HUD : Microsoft.Xna.Framework.DrawableGameComponent
    {
        private ContentManager Content;
        private SpriteBatch spriteBatch;
        private KaroGame game;

        private SpriteFont font;
        private Texture2D horizontalHud, hHudLeft, hHudRight, hHudMid;
        private Model whiteCone, redCone;

        private DateTime start;
        private DateTime pause;

        private bool isRunning;
        private bool isPaused;

        private Player player;

        private float posX = 0;
        private float posY = 0;
        private float timePosX = 0;
        private float timePosY = 0;
        private string timeString = "";
        private string currentPlayer = "";

        private Matrix world, view, proj, yRotation, translate;



        public HUD(Game game)
            : base(game)
        {
            // TODO: Construct any child components here
            this.Content = game.Content;
            this.game = (KaroGame)game;
        }

        /// <summary>
        /// Allows the game component to perform any initialization it needs to before starting
        /// to run.  This is where it can query for any required services and load content.
        /// </summary>
        public override void Initialize()
        {
            // TODO: Add your initialization code here

            translate = Matrix.CreateTranslation(3.65f, 3.75f, 0f);
           
            yRotation = Matrix.Identity;

            world = Matrix.CreateScale(0.6f) * Matrix.CreateTranslation(new Vector3(0, 0, -0.15f)) * Matrix.CreateRotationY(MathHelper.ToRadians(20));
            view = game.BasicEffect.View;
            proj = game.BasicEffect.Projection;

            base.Initialize();
        }

        public new void LoadContent()
        {
            horizontalHud = Content.Load<Texture2D>("HUD/HUD2");
            hHudLeft = Content.Load<Texture2D>("HUD/HHUDleft");
            hHudMid = Content.Load<Texture2D>("HUD/HHUDmid");
            hHudRight = Content.Load<Texture2D>("HUD/HHUDright");

            font = Content.Load<SpriteFont>("Font/MenuElement");

            redCone = Content.Load<Model>("RedConeSmall");
            whiteCone = Content.Load<Model>("WhiteConeSmall");

            this.spriteBatch = new SpriteBatch(game.GraphicsDevice);
            base.LoadContent();
        }

        /// <summary>
        /// Allows the game component to update itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        public override void Update(GameTime gameTime)
        {
            // TODO: Add your update code here
            yRotation *= Matrix.CreateRotationZ( MathHelper.ToRadians( 2 ) );
                    
            if (isRunning)
            {
                posX = 0;
                posY = 0;
                timePosX = 0;
                timePosY = 0;
                timeString = "";

                if (!game.IsBusy)
                {
                    currentPlayer = "Player:        " ;
                    player = Engine.currentBoard.OppositePlayer;
                }
                DateTime currentTime = !isPaused ? DateTime.Now : pause;

                timeString += ((currentTime - start).Minutes < 10)
                                      ? "0" + (currentTime - start).Minutes.ToString()
                                      : (currentTime - start).Minutes.ToString();

                timeString += " : ";

                timeString += (currentTime - start).Seconds < 10
                                      ? "0" + (currentTime - start).Seconds.ToString()
                                      : (currentTime - start).Seconds.ToString();

                switch (SettingsManager.Instance.HudPosition)
                {
                    case HudPosition.Top:
                        posX = ((float)game.Window.ClientBounds.Width / 2) -
                               ((float)horizontalHud.Width / 2);
                        timePosX = (float)game.Window.ClientBounds.Width / 2;
                        timePosY = posY + ((float)horizontalHud.Height / 2);
                        break;

                    case HudPosition.Bottom:
                        posX = ((float)game.Window.ClientBounds.Width / 2) -
                               ((float)horizontalHud.Width / 2);
                        posY = game.Window.ClientBounds.Height + 150 - horizontalHud.Width;

                        timePosX = (float)game.Window.ClientBounds.Width / 2;
                        timePosY = posY + ((float)horizontalHud.Height / 2);
                        break;

                    case HudPosition.Left:

                        break;
                    case HudPosition.Right:

                        break;

                }
            }
            base.Update(gameTime);
        }

        public override void Draw(GameTime gameTime)
        {
            // TODO: add draw code here
            Model playerTurnModel = null;

            switch (player)
            {
                case Player.Red:
                    playerTurnModel = redCone;
                    break;
                case Player.White:
                    playerTurnModel = whiteCone;
                    break;

            }


            spriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.Deferred, SaveStateMode.SaveState);

            if (SettingsManager.Instance.HudPosition == HudPosition.Top || SettingsManager.Instance.HudPosition == HudPosition.Bottom)
            {
                spriteBatch.Draw(horizontalHud, new Vector2(posX, posY), Color.White);
                posX += horizontalHud.Width + 20;

                spriteBatch.Draw(hHudLeft, new Vector2(posX, posY), Color.White);
                posX += hHudLeft.Width;

                float midPosX = posX;
                for (int i = 0; i < 3; i++)
                {
                    spriteBatch.Draw(hHudMid, new Vector2(midPosX, posY), Color.White);
                    midPosX += hHudMid.Width;
                }

                spriteBatch.Draw(hHudRight, new Vector2(midPosX, posY), Color.White);

                spriteBatch.DrawString(font, currentPlayer, new Vector2(posX + hHudMid.Width + hHudMid.Width, timePosY), new Color(253, 255, 188), 0, (font.MeasureString(currentPlayer) / 2), 1, SpriteEffects.None, 0.5f);
                spriteBatch.DrawString(font, timeString, new Vector2(timePosX, timePosY), new Color(253, 255, 188), 0, (font.MeasureString(timeString) / 2), 1, SpriteEffects.None, 0.5f);
            }

            spriteBatch.End();

            if (playerTurnModel != null)
            {
                foreach (ModelMesh mesh in playerTurnModel.Meshes)
                {
                    foreach (BasicEffect effect in mesh.Effects)
                    {
                        effect.EnableDefaultLighting();
                        effect.World = world * yRotation * translate;
                        effect.View = view;
                        effect.Projection = proj;

                        effect.PreferPerPixelLighting = true;
                    }
                    mesh.Draw();
                }
            }
            base.Draw(gameTime);
        }

        public void Start()
        {
            start = DateTime.Now;
            
            isRunning = true;
        }

        public void Pause()
        {
            if (!isPaused)
            {
                pause = DateTime.Now;
                isPaused = true;
            }
            else
            {
                TimeSpan elapsedTime = pause - start;
                start = DateTime.Now.Subtract(elapsedTime);
                isPaused = false;
            }
        }

        public void Reset()
        {
            start = DateTime.Now;
            pause = DateTime.Now;
        }
    }
}